package cre.sample.test.lock.latch;

import cre.sample.test.lock.MyAQS;

import java.util.concurrent.CountDownLatch;

/**
 * Created by CreGu on 2016/6/22.
 */
public class MyCountDownLatch extends CountDownLatch {

    private final Sync sync;



    /**
     * Constructs a {@code CountDownLatch} initialized with the given count.
     *
     * @param count the number of times {@link #countDown} must be invoked
     *              before threads can pass through {@link #await}
     * @throws IllegalArgumentException if {@code count} is negative
     */
    public MyCountDownLatch(int count) {
        super(count);
        if (count < 0) throw new IllegalArgumentException("count < 0");
        this.sync = new Sync(count);
    }

    @Override
    public void await() throws InterruptedException {
        sync.acquireSharedInterruptibly(1);

    }

    private static final class Sync extends MyAQS {
        private static final long serialVersionUID = 4982264981922014374L;

        Sync(int count) {
            setState(count);
        }

        int getCount() {
            return getState();
        }

        protected int tryAcquireShared(int acquires) {
            System.out.println("in MyCountDownLatch");
            System.out.println(super.toString());
            return (getState() == 0) ? 1 : -1;
        }

        protected boolean tryReleaseShared(int releases) {
            // Decrement count; signal when transition to zero
            for (;;) {
                int c = getState();
                if (c == 0)
                    return false;
                int nextc = c-1;
                if (compareAndSetState(c, nextc))
                    return nextc == 0;
            }
        }
    }
}
